<template>
  <div class="drawing-container">
    <canvas 
      ref="canvasRef"
      :width="canvasWidth"
      :height="canvasHeight"
      @mousedown="handleMouseDown"
      @mousemove="handleMouseMove"
      @mouseup="handleMouseUp"
      @mouseleave="handleMouseUp"
    ></canvas>
    <div class="toolbar">
      <div class="tool-group">
        <button @click="currentTool = 'pen'" :class="{ active: currentTool === 'pen' }">曲线</button>
        <button @click="currentTool = 'arrow'" :class="{ active: currentTool === 'arrow' }">箭头</button>
        <button @click="clearCanvas">清除</button>
        <button @click="isDraggable = !isDraggable" :class="{ active: isDraggable }">
          {{ isDraggable ? '锁定' : '解锁' }}
        </button>
      </div>
      <div class="tool-group">
        <label>线宽：</label>
        <input 
          type="range" 
          v-model="lineWidth" 
          min="1" 
          max="20" 
          step="1"
        />
        <span>{{ lineWidth }}px</span>
      </div>
      <div class="tool-group">
        <label>颜色：</label>
        <input 
          type="color" 
          v-model="strokeColor"
        />
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

// Canvas 配置
const canvasWidth = 800
const canvasHeight = 600
const canvasRef = ref(null)
let ctx = null
let devicePixelRatio = 1

// 工具状态
const currentTool = ref('pen')
const lineWidth = ref(2)
const strokeColor = ref('#000000')
const isDraggable = ref(true)

// 绘制状态
const isDrawing = ref(false)
const isDragging = ref(false)
const currentShape = ref(null)
const selectedShape = ref(null)
const dragOffset = ref({ x: 0, y: 0 })
const shapes = ref([])
const startPoint = ref(null)  // 修改为 null 初始值
const minDragDistance = 5

// 初始化 Canvas
onMounted(() => {
  const canvas = canvasRef.value
  devicePixelRatio = window.devicePixelRatio || 1
  
  // 设置 canvas 的实际尺寸
  canvas.width = canvasWidth * devicePixelRatio
  canvas.height = canvasHeight * devicePixelRatio
  
  // 设置 canvas 的显示尺寸
  canvas.style.width = `${canvasWidth}px`
  canvas.style.height = `${canvasHeight}px`
  
  ctx = canvas.getContext('2d')
  
  // 根据设备像素比缩放上下文
  ctx.scale(devicePixelRatio, devicePixelRatio)
  
  redraw()
})

// 鼠标事件处理
function handleMouseDown(e) {
  const rect = canvasRef.value.getBoundingClientRect()
  const x = (e.clientX - rect.left) * (canvasWidth / rect.width)
  const y = (e.clientY - rect.top) * (canvasHeight / rect.height)

  startPoint.value = { x, y }
  
  // 检查是否点击到了现有图形
  selectedShape.value = findShapeAtPosition(x, y)
  if (selectedShape.value) {
    // 只有在解锁状态下才能拖拽图形
    if (isDraggable.value) {
      isDragging.value = true
      isDrawing.value = false
      const shapeAnchorX = selectedShape.value.type === 'pen' ? 
        selectedShape.value.points[0][0] : 
        selectedShape.value.start.x
      const shapeAnchorY = selectedShape.value.type === 'pen' ? 
        selectedShape.value.points[0][1] : 
        selectedShape.value.start.y
        
      dragOffset.value = {
        x: x - shapeAnchorX,
        y: y - shapeAnchorY
      }
      selectedShape.value.initialAnchor = { x: shapeAnchorX, y: shapeAnchorY }
      redraw()
    }
    // 无论是否在解锁状态，点击到图形时都不进行绘制
    return
  }

  // 只有在点击空白区域时才开始绘制
  isDrawing.value = true
  currentShape.value = null
}

function handleMouseMove(e) {
  const rect = canvasRef.value.getBoundingClientRect()
  const x = (e.clientX - rect.left) * (canvasWidth / rect.width)
  const y = (e.clientY - rect.top) * (canvasHeight / rect.height)

  // 如果鼠标没有按下，直接返回
  if (!startPoint.value) {
    return
  }

  // 如果正在拖拽现有图形
  if (isDragging.value && selectedShape.value) {
    const deltaX = x - startPoint.value.x
    const deltaY = y - startPoint.value.y
    
    const newAnchorX = selectedShape.value.initialAnchor.x + deltaX
    const newAnchorY = selectedShape.value.initialAnchor.y + deltaY

    moveShapeTo(selectedShape.value, newAnchorX, newAnchorY)
    redraw()
    return
  }

  // 如果不在绘制状态，不进行绘制
  if (!isDrawing.value) {
    return
  }

  // 计算移动距离
  const dx = x - startPoint.value.x
  const dy = y - startPoint.value.y
  const distance = Math.sqrt(dx * dx + dy * dy)

  // 如果移动距离小于最小距离，不进行绘制
  if (distance < minDragDistance) {
    return
  }

  // 开始绘制新图形
  if (!currentShape.value) {
    if (currentTool.value === 'pen') {
      currentShape.value = {
        type: 'pen',
        points: [[startPoint.value.x, startPoint.value.y], [x, y]],
        stroke: strokeColor.value,
        lineWidth: lineWidth.value
      }
      shapes.value.push(currentShape.value)
    } else if (currentTool.value === 'arrow') {
      currentShape.value = {
        type: 'arrow',
        start: { x: startPoint.value.x, y: startPoint.value.y },
        end: { x, y },
        stroke: strokeColor.value,
        lineWidth: lineWidth.value
      }
      shapes.value.push(currentShape.value)
    }
  } else {
    // 更新现有图形
    if (currentTool.value === 'pen') {
      currentShape.value.points.push([x, y])
    } else if (currentTool.value === 'arrow') {
      currentShape.value.end = { x, y }
    }
  }

  redraw()
}

function handleMouseUp() {
  if (isDragging.value) {
    isDragging.value = false
    selectedShape.value = null
  } else {
    isDrawing.value = false
    currentShape.value = null
  }
  startPoint.value = null
}

// 绘制函数
function drawArrow(ctx, start, end, lineWidth) {
  const minHeadLength = 15
  const maxHeadLength = 30
  const headLength = Math.min(maxHeadLength, Math.max(minHeadLength, lineWidth * 4))
  
  const angle = Math.atan2(end.y - start.y, end.x - start.x)
  
  const baseX = end.x - headLength * Math.cos(angle)
  const baseY = end.y - headLength * Math.sin(angle)
  
  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(baseX, baseY)
  ctx.stroke()

  const baseWidth = headLength * 2 / Math.sqrt(3)
  const halfBaseWidth = baseWidth / 2

  const baseAngle1 = angle + Math.PI / 2
  const baseAngle2 = angle - Math.PI / 2
  
  const baseX1 = baseX + halfBaseWidth * Math.cos(baseAngle1)
  const baseY1 = baseY + halfBaseWidth * Math.sin(baseAngle1)
  const baseX2 = baseX + halfBaseWidth * Math.cos(baseAngle2)
  const baseY2 = baseY + halfBaseWidth * Math.sin(baseAngle2)

  const cornerRadius = Math.min(4, headLength * 0.1)

  ctx.beginPath()
  
  ctx.moveTo(end.x, end.y)
  
  const controlX1 = end.x - (end.x - baseX1) * 0.2
  const controlY1 = end.y - (end.y - baseY1) * 0.2
  
  const controlX2 = baseX1 + (baseX - baseX1) * 0.2
  const controlY2 = baseY1 + (baseY - baseY1) * 0.2
  
  ctx.quadraticCurveTo(controlX1, controlY1, baseX1, baseY1)
  ctx.quadraticCurveTo(controlX2, controlY2, baseX, baseY)
  
  const controlX3 = baseX + (baseX2 - baseX) * 0.2
  const controlY3 = baseY + (baseY2 - baseY) * 0.2
  
  const controlX4 = baseX2 + (end.x - baseX2) * 0.2
  const controlY4 = baseY2 + (end.y - baseY2) * 0.2
  
  ctx.quadraticCurveTo(controlX3, controlY3, baseX2, baseY2)
  ctx.quadraticCurveTo(controlX4, controlY4, end.x, end.y)
  
  ctx.closePath()
  ctx.fill()
}

function redraw() {
  if (!ctx) {
    console.error('Canvas context is not initialized')
    return
  }

  // 使用 clearRect 清除画布，保持透明
  ctx.clearRect(0, 0, canvasWidth, canvasHeight)

  shapes.value.forEach(shape => {
    ctx.strokeStyle = shape.stroke
    ctx.fillStyle = shape.stroke
    ctx.lineWidth = shape.lineWidth
    ctx.lineCap = 'round'
    ctx.lineJoin = 'round'

    if (shape.type === 'pen') {
      ctx.beginPath()
      ctx.moveTo(shape.points[0][0], shape.points[0][1])
      for (let i = 1; i < shape.points.length; i++) {
        ctx.lineTo(shape.points[i][0], shape.points[i][1])
      }
      ctx.stroke()
    } else if (shape.type === 'arrow') {
      drawArrow(ctx, shape.start, shape.end, shape.lineWidth)
    }
  })
}

function clearCanvas() {
  shapes.value = []
  redraw()
}

function findShapeAtPosition(x, y) {
  for (let i = shapes.value.length - 1; i >= 0; i--) {
    const shape = shapes.value[i]
    if (shape.type === 'pen') {
      for (let j = 0; j < shape.points.length - 1; j++) {
        const p1 = shape.points[j]
        const p2 = shape.points[j + 1]
        if (isPointNearLine(x, y, p1[0], p1[1], p2[0], p2[1], shape.lineWidth)) {
          return shape
        }
      }
    } else if (shape.type === 'arrow') {
      if (isPointNearLine(x, y, shape.start.x, shape.start.y, shape.end.x, shape.end.y, shape.lineWidth)) {
        return shape
      }
    }
  }
  return null
}

function isPointNearLine(px, py, x1, y1, x2, y2, lineWidth) {
  const A = px - x1
  const B = py - y1
  const C = x2 - x1
  const D = y2 - y1

  const dot = A * C + B * D
  const len_sq = C * C + D * D
  let param = -1

  if (len_sq !== 0) {
    param = dot / len_sq
  }

  let xx, yy

  if (param < 0) {
    xx = x1
    yy = y1
  } else if (param > 1) {
    xx = x2
    yy = y2
  } else {
    xx = x1 + param * C
    yy = y1 + param * D
  }

  const dx = px - xx
  const dy = py - yy
  const distance = Math.sqrt(dx * dx + dy * dy)

  return distance <= lineWidth * 2
}

function moveShape(shape, dx, dy) {
  if (shape.type === 'pen') {
    shape.points = shape.points.map(p => [p[0] + dx, p[1] + dy])
  } else if (shape.type === 'arrow') {
    shape.start = {
      x: shape.start.x + dx,
      y: shape.start.y + dy
    }
    shape.end = {
      x: shape.end.x + dx,
      y: shape.end.y + dy
    }
  }
}

function moveShapeTo(shape, targetAnchorX, targetAnchorY) {
  const currentAnchorX = shape.type === 'pen' ? shape.points[0][0] : shape.start.x;
  const currentAnchorY = shape.type === 'pen' ? shape.points[0][1] : shape.start.y;

  const deltaX = targetAnchorX - currentAnchorX;
  const deltaY = targetAnchorY - currentAnchorY;

  if (shape.type === 'pen') {
    shape.points = shape.points.map(p => [p[0] + deltaX, p[1] + deltaY]);
  } else if (shape.type === 'arrow') {
    shape.start = { x: shape.start.x + deltaX, y: shape.start.y + deltaY };
    shape.end = { x: shape.end.x + deltaX, y: shape.end.y + deltaY };
  }
}
</script>

<style scoped>
.drawing-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

canvas {
  border: 1px solid #ccc;
  border-radius: 4px;
  background: transparent; /* 设置背景为透明 */
}

.toolbar {
  display: flex;
  gap: 20px;
  align-items: center;
  padding: 10px;
  background: #f5f5f5;
  border-radius: 4px;
}

.tool-group {
  display: flex;
  align-items: center;
  gap: 8px;
}

button {
  padding: 6px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  background: white;
  cursor: pointer;
}

button:hover {
  background: #f0f0f0;
}

button.active {
  background: #e0e0e0;
  border-color: #999;
}

input[type="range"] {
  width: 100px;
}

input[type="color"] {
  width: 40px;
  height: 24px;
  padding: 0;
  border: 1px solid #ccc;
  border-radius: 4px;
}
</style>
